代理模式 Proxy Pattern

为另一个对象提供替身或者占位符以控制这个对象的访问。

通常代理类内含有一个被代理类的引用。

类图

代理分类

远程代理

通过 RMI 和 JNDI 进行远程方法调用,在不同 JVM 中进行交互。

虚拟代理

通常利用代理对象来创建和销毁占用较多资源的被代理对象。用来延迟大资源对象的创建。

动态代理 Dynamic Proxy

java.lang.reflect.Proxy

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类

InvocationHandler

是代理实例的调用处理程序实现的接口,每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

动态Proxy是这样的一种类:

它是在运行生成的类,在生成时你必须提供一组Interface给它,然后该class就宣称它实现了这些interface。你可以把该class的实例当作这些interface中的任何一个来用。当然,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。

在使用动态代理类时,我们必须实现InvocationHandler接口

步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//1、定义抽象角色 [共同的接口] :动态代理的使用,体会反射是动态语言的关键
interface Subject {
void action();
}

//2、定义真实角色 :被代理类
class RealSubject implements Subject {
public void action() {
System.out.println( "我是被代理类,记得要执行我!" );
}
}

//3、定义代理角色 :定义代理类
class MyInvocationHandler implements InvocationHandler {
Object obj;// 实现了接口的被代理类的对象的声明

// 作用:①给被代理的对象实例化②返回一个代理类的对象
public Object blind(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}
//当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//method方法的返回值时returnVal
Object returnVal = method.invoke(obj, args);
return returnVal;
}
}

//测试类
public class TestProxy {
public static void main(String[] args) {
//1.被代理类的对象
RealSubject real = new RealSubject();
//2.创建一个实现了InvacationHandler接口的代理类的对象
MyInvocationHandler handler = new MyInvocationHandler();
//3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。
Object obj = handler.blind(real);
Subject sub = (Subject)obj; //此时sub就是代理类的对象
sub.action(); //转到对InvacationHandler接口的实现类的invoke()方法的调用

}
}